/**
 * 
 * Copyright 2009 Marco Speranza <marco.speranza79@gmail.com>
 *    
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *   
 * http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.commons.util.conversion;

/**
 * Procedura di utilita' per convertire valori esadecimali in decimali, e viceversa.
 * 
 * @author Marco Speranza
 */

public final class HexConv {
	/**
	 * Converte in un intero il numero esadecimale contenuto nel byte in input.
	 * @param b il byte da convertire
	 * @return il valore decimale calcolato
	 */
	public static int hexInt(byte b) {
		int value = (int) b;
		return ( value < 0 ) ? value + 256 : value;
	} // end hexInt()

	/**
	 * Converte in un decimale il numero esadecimale contenuto nel buffer in input	 * (su 2 byte), assumendo il Big Endian order: MSB, LSB.
	 * @param buffer il buffer contenente la word (MSB, LSB)
	 * @param offset la posizione in cui inizia la word
	 * @return il valore decimale corrispondente
	 */
	public static int hexInt(byte[] buffer, int offset) {
		return HexConv.hexInt(buffer[offset], buffer[offset+1]);
	} // end hexInt()

	/**
	 * Converte in un decimale il numero esadecimale in input.
	 * @param msb il byte pi� significativo
	 * @param lsb il byte meno significativo
	 * @return il valore decimale corrispondente
	 */
	public static int hexInt(byte msb, byte lsb) {
		int iMsb = HexConv.hexInt(msb);
		int iLsb = HexConv.hexInt(lsb);
		return (iMsb * 256 + iLsb);
	} // end hexInt()

	/**
	 * Converte in un float il numero esadecimale contenuto nel buffer in input (su 4 byte).
	 * Assume il seguente ordine: LsbL, Lsb, Msb, MsbM
	 * @param buffer il buffer contenente la word (LL, L, M, MM)
	 * @param offset la posizione da cui inizia la word
	 * @return il valore float calcolato.
	 */
	public static float bufferToFloat(byte[] buffer, int offset) {
		int	v0 = HexConv.hexInt(buffer[offset]);
		int v1 = HexConv.hexInt(buffer[offset + 1]);
		int v2 = HexConv.hexInt(buffer[offset + 2]);
		int v3 = HexConv.hexInt(buffer[offset + 3]);

		// 16777216 = 65536 * 256
		int value = v3 * 16777216;
		value += (v2 * 65536);
		value += (v1 * 256);
		value += v0;

		float	risultato = Float.intBitsToFloat(value);
		return risultato;
	} // end bufferToFloat()

	/**
	 * Restituisce una stringa che rappresenta un numero intero in formato
	 * esadecimale espresso su tante cifre quanto specificato, quindi con
	 * eventuali 0 (zero) davanti.
	 * @param value il numero intero da rappresentare in esadecimale
	 * @param digit le cifre con cui costruire la stringa
	 * @return la stringa formattata.
	 */
	private static String hexString(int value, int digit) {
		String	s = "0000" + Integer.toHexString(value);
		return s.substring(s.length() - digit);
	} // end hexString()

	/**
	 * Converte in una stringa di due cifre esadecimali il valore in input.
	 * @param value il byte da convertire
	 * @return la stringa formattata.
	 */
	public static String hexString(byte value) {
		return hexString( (int)value, 2 );
	} // end hexString()

	/**
	 * Rappresenta un buffer di bytes in una stringa di numeri esadecimali;
	 * ogni 16 valori ritorna a capo per una nuova linea.
	 * @param data il buffer da convertire in stringa
	 * @param ofst la posizione da cui cominciare la conversione
	 * @param len la dimensione del buffer
	 * @return la stringa formattata.
	 */
	public static String dumpBufferToString(byte[] data, int ofst, int len) {
		String	s = "";
		int		pos = 0;

		for(int i = 0; i < len; i++) {
			s += HexConv.hexString(data[ofst + i]) + " ";
			pos++;
			if ( pos == 16 ) {
				s = s + "\r\n";
				pos = 0;
			}
		}
		return s;
	} // end dumpBufferToString()

	/**
	 * Rappresenta un buffer di bytes in una stringa di numeri esadecimali.
	 * @param data il buffer da convertire in stringa
	 * @param ofst la posizione da cui cominciare la conversione
	 * @param len la dimensione del buffer
	 * @return la stringa formattata.
	 */
	public static String bufferToString(byte[] data, int ofst, int len) {
		StringBuffer sb = new StringBuffer();

		for(int i = 0; i < len; i++) {
			sb.append( HexConv.hexString(data[ofst+i]) );
			sb.append(" ");
		}
		return sb.toString().trim();
	} // end bufferToString()
}
